# Copyright (C) 2006  Apptility LLC  http://www.apptility.com
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA


class UserController < ApplicationController
  # Define default Main Tab Name
    $CURRENT_MAIN_TAB_NAME = "Users"

  
  # The action used to log a user in. If the user was redirected to the login page
  # by the login_required method, they should be sent back to the page they were
  # trying to access. If not, they will be sent to "/user/home".
  def login
    if session[:user]==nil
      return if generate_blank
      @user = User.new(params[:user])
      if session[:user] = User.authenticate(params[:user][:login], params[:user][:password])
        session[:user].logged_in_at = Time.now
        session[:user].save
        flash[:simplemsg] = 'Login successful'
        #print "Login Successful##########"
        # redirect_to_stored_or_default :action => 'home'
        redirect_to :controller => "/dashboard", :action => "home"
      else
        @login = params[:user][:login]
        flash.now[:message] = 'Login unsuccessful'
      end
    else
      redirect_to :controller => "/dashboard", :action => "home" 
    end  
  end
   
  def list
   # NagiosDataUpdater.get_host_groups
    @user = current_user
    # @content_columns = User.content_columns
    @content_columns = user_content_columns_to_display
    #User.benchmark("############USER LIST#################", Logger::DEBUG, false) do   
    #@users_by_org_id = User.find(:all, :conditions => [ "organization_id =?", @user.organization_id])
    #@user_pages, @users_by_org_id = Paginator.new self, User.count, 10
    #@user_pages, @users_by_org_id = paginate :user, :per_page => 10 
    if is_current_user_enterprise_admin
      @user_pages, @users_by_org_id = paginate :user, :order_by => "firstname, lastname ASC", :per_page => 10
    else
      @user_pages, @users_by_org_id = paginate :user, :conditions => [ "organization_id =?", @user.organization_id], :order_by => "firstname, lastname ASC", :per_page => 10
    end
    
  end

  def forgot_password
    # Always redirect if logged in
    if user?
      flash[:message] = 'You are currently logged in. You may change your password now.'
      redirect_to :action => 'change_password'
      return
    end

    # Email disabled... we are unable to provide the password
    if !LoginEngine.config(:use_email_notification)
      flash[:message] = "Please contact the system admin at #{LoginEngine.config(:admin_email)} to reset your password."
      redirect_back_or_default :action => 'login'
      return
    end

    # Render on :get and render
    return if generate_blank

    # Handle the :post
    if params[:user][:email].empty?
      flash.now[:warning] = 'Please enter a valid email address.'
    elsif (user = User.find_by_email(params[:user][:email])).nil?
      flash.now[:warning] = "We could not find a user with the email address #{params[:user][:email]}"
    else
      begin
        User.transaction(user) do
          key = user.generate_security_token
          url = url_for(:action => 'change_password', :user_id => user.id, :key => key)
          UserNotify.deliver_forgot_password(user, url)
          flash[:simplemsg] = "Instructions on resetting your password have been emailed to #{params[:user][:email]}"
        end  
        unless user?
          redirect_to :action => 'login'
          return
        end
        redirect_back_or_default :action => 'home'
      rescue Exception => e
        flash.now[:warning] = "Your password could not be emailed to #{params[:user][:email]}" << e.message
      end
    end
  end


    def delete_user
      @user = User.find(params[:id])
      if(@user.destroy)
        flash[:message] = "User has been successfully deleted"
      else
        flash[:message] = "Error deleting user"
      end
      redirect_to :action => 'list'
    end
    
    #for search functionality of user
    
    def search 
       @login = params[:login]
       @firstname = params[:firstname]
       @lastname = params[:lastname]
       @emailaddress = params[:emailaddress]
       @query = 'SELECT * FROM users ';
       @whereclause = '';
       if(@login != '')
          if(@whereclause=='')
                 @whereclause = @whereclause +" WHERE login ='" + @login + "'"; 
          else
                @whereclause = @whereclause +" AND login ='" + @login + "'"; 
           end
       end 
       
       if(@firstname != '')
          if(@whereclause=='')
                 @whereclause = @whereclause +" WHERE firstname ='" + @firstname + "'"; 
          else
                @whereclause = @whereclause +" AND firstname ='" + @firstname + "'"; 
           end
       end 
       
       if(@lastname != '')
          if(@whereclause=='')
                 @whereclause = @whereclause +" WHERE lastname ='" + @lastname + "'"; 
          else
                @whereclause = @whereclause +" AND lastname ='" + @lastname + "'"; 
           end
       end 
       
       if(@emailaddress != '')
          if(@whereclause=='')
                 @whereclause = @whereclause +" WHERE email ='" + @emailaddress + "'"; 
          else
                @whereclause = @whereclause +" AND email ='" + @emailaddress + "'"; 
           end
       end   
       
       @query=@query + @whereclause;
       @users = User.find_by_sql [@query]
       @user_pages = Paginator.new self, User.count, 10
       @content_columns = user_content_columns_to_display
       @users_by_org_id = User.find_by_sql [@query]#,
                          #:order =>"last_name first_name ASC"#,
                          #:limit  =>  @user_pages.items_per_page
       
       #redirect_to :action => 'list'
       render :action => "list"
   end
 #end of search functionality
 
    def user_content_columns_to_display
      # Override this from user engine
      desired_columns = ["is_enterprise", "verified", "role", "created_at", "updated_at",  "created_by", "updated_by", "logged_in_at","deleted","delete_after","salted_password", "salt", "security_token", "token_expiry"]
      User.content_columns.delete_if { |c| desired_columns.include?(c.name) }
    end
    
  # Overwrite from Login Engine  
  # Register as a new user. Upon successful registration, the user will be sent to
  # "/user/login" to enter their details.
  def signup
    return if generate_blank
    params[:user].delete('form')
    @user = User.new(params[:user])
    #@org = Organization.new(params[:user])
    
    
    begin
      User.transaction(@user) do
        @user.new_password = true
        unless LoginEngine.config(:use_email_notification) and LoginEngine.config(:confirm_account)
          @user.verified = 1
        end
       
       # Following is not great way to validate, till I figure out validates_associate with 
       # user object.
        orgName = params[:organizationName]
        if(orgName.strip.length==0)
          flash[:notice] = 'Company name can not be blank'
          return 
        end  
        #ccount = Organization.find_by_sql["select count(*) from Organization where name=?",orgName]
        @ccount = Organization.find(:all, :conditions => [ "name =?", orgName])
        if(@ccount.length>=1)
          flash[:notice] = 'Weeew!, Company name already exists. Change the company name to proceed'
          return 
        end
        
       
        if @user.save
          print "after save"
          key = @user.generate_security_token
          print "after generate_security_token"
          url = url_for(:action => 'home', :user_id => @user.id, :key => key)
          flash[:simplemsg] = 'Signup successful! Please log in.'
          print "after successful!"
          if LoginEngine.config(:use_email_notification) and LoginEngine.config(:confirm_account)
            UserNotify.deliver_signup(@user, params[:user][:password], url)
            flash[:simplemsg] << ' Please check your registered email account to verify your account registration and continue with the login.'
          end
          
          @org = Organization.new
          @org.name = orgName
          @org.save
          @user.organization_id = @org.id
          @user.save
#          admin_role = Role.find_by_name(UserEngine.config(:admin_role_name))
#          if admin_role
#            @user.roles << admin_role
#          end   
          redirect_to :action => 'login'
        end
      end
    rescue Exception => e
      flash.now[:notice] = nil
      flash.now[:warning] = 'Error creating account: confirmation email not sent:'+e.message
      logger.error "Unable to send confirmation E-Mail:"
      logger.error e
    end
  end
  
  def logout
     session[:user] = nil
     redirect_to :action => 'login'
  end
  
 ######## Added following to fix the Url routing error
 #after setup wizard redirection to user/login
 # will figure out why?. Later..   
    # Generate a template user for certain actions on get
   def generate_blank
     case request.method
     when :get
       @user = User.new
       render
       return true
     end
     return false
   end

 # Create a new User, skipping any verification by email.
  def new
    AjubyLogger.logInfo "RM: #{request.method}"
    case request.method
      when :get
        @user = User.new
        render
        return true
      when :post
        @user = User.new(params[:user])
        begin
          User.transaction(@user) do
            @user.new_password = true
            @user.verified = 1 # skip verification, because we are ADMIN!
            if @user.save
              flash[:notice] = 'User has been successfully created.'
              redirect_to :action => 'list'
            end
          end
        rescue Exception => e
          flash.now[:notice] = nil
          flash.now[:warning] = 'Error creating account: confirmation email not sent'
          logger.error e
        end
    end
  end
     
  # Display the details for a given user
  def show    
    if (@user_check = find_user(params[:id]))
     @content_columns = user_content_columns_to_display
    else
      redirect_back_or_default :action => 'list'
    end
  end

  def edit
    edit_user
  end
  
  # Edit the details of any user. The Role which can perform this will almost certainly also
  # need the following permissions: user/change_password, user/edit, user/edit_roles, user/delete
  def edit_user
    if (@user_check = find_user(params[:id]))
      
      @is_admin = User.find(current_user.id)
      @check_admin = @is_admin.roles.find(:all, :conditions => [ "role_id =?" , "2"])
      for @is_check_admin in @check_admin
        @check =1 
      end

      if @user_check.id == current_user.id || @check ==1
        @user = @user_check
        
        @all_roles = Role.find_all.select { |r| r.name != UserEngine.config(:guest_role_name) }
        case request.method
          when :get
          when :post
          @user.attributes = params[:user].delete_if { |k,v| not LoginEngine.config(:changeable_fields).include?(k) }
          if @user.save
            flash.now[:simplemsg] = "Details for user '#{@user.login}' has been updated"
          else
            flash.now[:warning] = "Details could not be updated!"
          end
        end
      else
        flash[:warning] = "You are not authorised to edit other details"
        redirect_to :controller => 'dashboard', :action => 'home'
      end
    else
      redirect_back_or_default :action => 'list'
    end
  end

  # Edit the roles for a given User object.
  # A user typically shouldn't be allowed to edit their own roles, since they could
  # assign themselves as Admins and then do anything. Therefore, keep this method
  # locked down as much as possible.
  def edit_roles
    if (@user = find_user(params[:id]))
      begin
        User.transaction(@user) do
        
          roles = params[:user][:roles].collect { |role_id| Role.find(role_id) }
          # add any new roles & remove any missing roles
          roles.each { |role| @user.roles << role if !@user.roles.include?(role) }
          @user.roles.each { |role| @user.roles.delete(role) if !roles.include?(role) }

          @user.save
          flash[:simplemsg] = "Roles updated for user '#{@user.login}'."
        end
      rescue
        flash[:warning] = 'Roles could not be edited at this time. Please retry.'
      ensure
        redirect_to :back
      end
    else
      redirect_back_or_default :action => 'list'
    end
  end
  
  # Change the password of an arbitrary user
  def change_password_for_user
    if (@user = find_user(params[:id]))
      if(do_change_password_for(@user))
        flash[:simplemsg] = "Password for user '#{@user.login}' has been updated."
      end  
    end
    redirect_back_or_default :action => 'list'
  end

  protected
    # A convenience method to find a User, and add any errors to the flash if
    # the User is not found.
    def find_user(id)
      begin
        User.find(id)
      rescue ActiveRecord::RecordNotFound
        flash[:message] = "There is no user with ID ##{id}"
        nil
      end
    end  
    
     def do_change_password_for(user)
      begin
        User.transaction(user) do
          user.change_password(params[:user][:password], params[:user][:password_confirmation])
          if user.save
            if LoginEngine.config(:use_email_notification)
              UserNotify.deliver_change_password(user, params[:user][:password])
              flash[:simplemsg] = "Updated password emailed to #{@user.email}"
            else
              flash[:simplemsg] = "Password updated."
            end
            return true
          else
            flash[:warning] = 'There was a problem saving the password. Please retry.'
            return false
          end
        end
      rescue Exception => e
        flash[:warning] = 'Password could not be changed at this time. because : '<<e.message
        return false
      end
    end
     
     
    def is_current_user_enterprise_admin
      return current_user.is_enterprise=='y'? true: false
    end     
end
